/*
 * Copyright (C) 2025 ameise <ameise.wang@gmail.com> - All Rights Reserved
 *
 * This file is part of e3ds.
 *
 * e3ds is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * e3ds is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with e3ds. If not, see <https://www.gnu.org/licenses/>.
 */

package deque

import "sync"

func NewRingLock[T any](mu sync.Locker, cap int) *RingLock[T] {
	q := &RingLock[T]{q: NewRing[T](cap)}
	q.mu = mu
	return q
}

type RingLock[T any] struct {
	q  *Ring[T]
	mu sync.Locker
}

func (ts *RingLock[T]) ResetCap(cap int) error {
	ts.mu.Lock()
	err := ts.q.ResetCap(cap)
	ts.mu.Unlock()
	return err
}

func (ts *RingLock[T]) IsEmpty() bool {
	ts.mu.Lock()
	empty := ts.q.IsEmpty()
	ts.mu.Unlock()
	return empty
}

func (ts *RingLock[T]) Size() int {
	ts.mu.Lock()
	size := ts.q.Size()
	ts.mu.Unlock()
	return size
}

func (ts *RingLock[T]) PushFront(v T) error {
	ts.mu.Lock()
	err := ts.q.PushFront(v)
	ts.mu.Unlock()
	return err
}

func (ts *RingLock[T]) PushFrontBatch(vs []T) error {
	ts.mu.Lock()
	err := ts.q.PushFrontBatch(vs)
	ts.mu.Unlock()
	return err
}

func (ts *RingLock[T]) PushBack(v T) error {
	ts.mu.Lock()
	err := ts.q.PushBack(v)
	ts.mu.Unlock()
	return err
}

func (ts *RingLock[T]) PushBackBatch(vs []T) error {
	ts.mu.Lock()
	err := ts.q.PushBackBatch(vs)
	ts.mu.Unlock()
	return err
}

func (ts *RingLock[T]) PopFront() (T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopFront()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopFrontBatch(n int) ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopFrontBatch(n)
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopFrontHalf() ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopFrontHalf()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopFrontAll() ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopFrontAll()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopBack() (T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopBack()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopBackBatch(n int) ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopBackBatch(n)
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopBackHalf() ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopBackHalf()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopBackAll() ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopBackAll()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) Enqueue(v T) error {
	ts.mu.Lock()
	err := ts.q.Enqueue(v)
	ts.mu.Unlock()
	return err
}

func (ts *RingLock[T]) EnqueueBatch(vs []T) error {
	ts.mu.Lock()
	err := ts.q.EnqueueBatch(vs)
	ts.mu.Unlock()
	return err
}

func (ts *RingLock[T]) Peek() (T, error) {
	ts.mu.Lock()
	v, err := ts.q.Peek()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) Dequeue() (T, error) {
	ts.mu.Lock()
	v, err := ts.q.Dequeue()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) DequeueBatch(n int) ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.DequeueBatch(n)
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) DequeueHalf() ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.DequeueHalf()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) DequeueAll() ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.DequeueAll()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) Push(v T) error {
	ts.mu.Lock()
	err := ts.q.Push(v)
	ts.mu.Unlock()
	return err
}

func (ts *RingLock[T]) PushBatch(vs []T) error {
	ts.mu.Lock()
	err := ts.q.PushBatch(vs)
	ts.mu.Unlock()
	return err
}

func (ts *RingLock[T]) Pop() (T, error) {
	ts.mu.Lock()
	v, err := ts.q.Pop()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopBatch(n int) ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopBatch(n)
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopHalf() ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopHalf()
	ts.mu.Unlock()
	return v, err
}

func (ts *RingLock[T]) PopAll() ([]T, error) {
	ts.mu.Lock()
	v, err := ts.q.PopAll()
	ts.mu.Unlock()
	return v, err
}
